package com.qudian.pay.redis.support;

import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import com.google.common.collect.Lists;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
import redis.clients.util.Pool;

public class ShardedJedisPoolFactory implements DisposableBean, FactoryBean<Pool<ShardedJedis>> {
	
	private static final String HASH_HEAD = "instance:";
	
	private Pool<ShardedJedis> jedisPool;
	
	private String servers;
	
	private JedisPoolConfig jedisPoolConfig;
	
	private Integer timeout = 2000;
	
	@Override
	public void destroy() throws Exception {
		jedisPool.destroy();
	}
	
	@Override
	public Pool<ShardedJedis> getObject() {
		if (null == jedisPool) {
			this.jedisPool = this.create();
		}
		return jedisPool;
	}
	
	@Override
	public Class<?> getObjectType() {
		return ShardedJedisPool.class;
	}
	
	@Override
	public boolean isSingleton() {
		return true;
	}
	
	private ShardedJedisPool create() {
		if (StringUtils.isBlank(this.servers)) return null;
		String[] redisList = StringUtils.split(this.servers, ";");
		List<JedisShardInfo> shards = Lists.newArrayListWithExpectedSize(redisList.length);
		for (int i = 0; i < redisList.length; i++) {
			String[] splitStr = StringUtils.split(redisList[i], ":");
			String host = StringUtils.trim(splitStr[0]);
			Integer port = Integer.valueOf(StringUtils.trim(splitStr[1]));
			JedisShardInfo jedisInfo = new JedisShardInfo(host, port, timeout, HASH_HEAD + i);
			if(splitStr.length > 2) {
				String password = StringUtils.trim(splitStr[2]);
				jedisInfo.setPassword(password);
			}
			shards.add(jedisInfo);
		}
		return new ShardedJedisPool(this.jedisPoolConfig, shards);
	}
	
	public void setServers(String servers) {
		this.servers = servers;
	}
	
	public void setJedisPoolConfig(JedisPoolConfig jedisPoolConfig) {
		this.jedisPoolConfig = jedisPoolConfig;
	}
	
	public void setTimeout(Integer timeout) {
		this.timeout = timeout;
	}
}
